#ifndef __QTCH_INFOPUSH_WECOM_PUSHER_H__
#define __QTCH_INFOPUSH_WECOM_PUSHER_H__

#include <string.h>
#include <memory>
#include <vector>
#include <unordered_map>


#include "qtch/mutex.h"
#include "qtch/singleton.h"
#include "qtch/http/http.h"
#include "qtch/infoPush/WXBizMsgCrypt.h"

namespace qtch {
namespace infoPush {

class WeComPusher {
public:
    typedef std::shared_ptr<WeComPusher> ptr;
    typedef qtch::RWMutex RWMutexType;

    enum PushType{
        NONE,
        TEXT,
        IMAGE,
        VOICE,
        VIDEO,
        FILE
    };

    const std::string pushTypeToString(PushType type);

    WeComPusher(const std::string& corpid,const std::string& secret
            , const std::string& agentid);

    /**
     * @brief 判断access token 是否过期
     * 
     * @return true 
     * @return false 
     */
    bool isAccessTokenExpire();

    /**
     * @brief 重新获取access token
     * 
     * @param force 是否强制重新获取access token
     * @return true 
     * @return false 
     */
    bool reflashAccessToken(bool force=false);


    /**
     * @brief 发送文本信息给用户
     * 
     * @param content 要发送的信息
     * @param send_user 用户id, 如果send_user为空，则使用默认发送人员
     * @return true 发送成功
     * @return false 发送失败
     */
    bool sendTextMessageToUser(const std::string& content,const std::string& send_user);

    bool UploadMedia(PushType type ,const std::string& data,std::string& media_id);

    bool sendMediaMessage(PushType type ,const std::string& media_id,const std::string& send_user);

    bool httpSend(qtch::http::HttpMethod method,const std::string& url,const std::string& data);


    const std::string& getAccessToken();
    
    void setCorpid(const std::string& v){ m_corpid = v;}
    void setSecret(const std::string& v){ m_secret = v;}
    void setAgentid(const std::string& v) {m_agentid = v;}

    int32_t getErrorCode() const {return m_errorCode;}
    const std::string& getErrorMessage()const {return m_errorMessage;}

    


private:
    std::string m_corpid;
    std::string m_secret;
    RWMutexType m_mutex;

    


    // 访问企业微信的 access_token
    std::string m_access_token;

    // 应用id
    std::string m_agentid;

    // 企业微信的 access_token 的过期时间
    int64_t m_access_token_expire_time;

    int32_t m_errorCode;

    std::string m_errorMessage;

};

class WeComPusherManager {
public:
    typedef std::shared_ptr<WeComPusherManager> ptr;
    typedef qtch::RWMutex RWMutexType;

    void init(const std::string& corpid,const std::string& token,const std::string& encodeAESKey);

    void addWecom(const std::string& name,const std::string& corpid
        ,const std::string& secret,const std::string& agentid);

    void delWecom(const std::string& name);

    WeComPusher::ptr getWecom(const std::string& name);

    void setCorpid(const std::string& v) {m_corpid = v;}
    void setToken(const std::string& v) {m_token = v;}
    void setEncodingAESKey(const std::string& v){m_encodingAESKey = v;}
    

    WXBizMsgCrypt::ptr getCrypt();

private:
    // 企业id
    std::string m_corpid;

    std::string m_token;
    std::string m_encodingAESKey;

    std::unordered_map<std::string, WeComPusher::ptr> m_data;
    RWMutexType m_mutex;


};

typedef qtch::Singleton<WeComPusherManager> WeComMgr;

class WeComPusherBuild : public std::enable_shared_from_this<WeComPusherBuild>{
public:
    typedef std::shared_ptr<WeComPusherBuild> ptr;

    static WeComPusherBuild::ptr build(const std::string& name);

    WeComPusherBuild::ptr addUser(const std::string& userid);

    WeComPusherBuild::ptr toAllUser();

    WeComPusherBuild::ptr sendTextMessage(const std::string& text);

    WeComPusherBuild::ptr sendVideoMessage(const std::string& video);

    WeComPusherBuild::ptr sendImageMessage(const std::string& image);

    WeComPusherBuild::ptr sendVoiceMessage(const std::string& voice);

    WeComPusherBuild::ptr sendFileMessage(const std::string& file);

    WeComPusherBuild::ptr sendMediaId(WeComPusher::PushType type,const std::string& media_id);

    WeComPusherBuild::ptr sendType(WeComPusher::PushType type,const std::string& data);

    bool send();

    std::string getSendUsers(); 

    int32_t getErrorCode() const {return m_errorCode;}
    const std::string& getErrorMessage()const {return m_errorMessage;}

private:
    WeComPusherBuild(std::string name);

private:
    
    // 使用应用名
    std::string m_name;

    bool m_isToAllUser;

    //发送的用户
    std::vector<std::string> m_send_users;

    // 发送消息的类型
    WeComPusher::PushType m_type;

    // m_type 为 TEXT 时有效，为发送的消息
    std::string m_content;

    // m_type 不为 TEXT 时有效，表明媒体文件上传后获取的唯一标识，3天内有效
    std::string m_media_id;

    std::string m_media_data;

    int32_t m_errorCode;

    std::string m_errorMessage;
    
};


}
}






#endif